package com.acdc.mqtt.service.impl;

import com.acdc.mqtt.service.MessageHandler;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

import com.acdc.dlt698.parser.ConnectResponseFrameParser;
import com.acdc.dlt698.parser.GetResponseNormalFrameParser;
import com.acdc.mqtt.entity.MqttMsg;
import com.acdc.mqtt.entity._485Ack;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.acdc.dlt698.utils.HexUtils;
import com.acdc.dlt698.entity.GetResponseNormalFrame;
import com.acdc.dlt698.entity.ForwardPower;
import com.acdc.device.service.IMeterDeviceService;
import com.acdc.dlt698.entity.ConnectResponseFrame;
import com.acdc.service.IIotModuleService;
import com.acdc.domain.IotModule;
import com.acdc.device.domain.MeterDevice;
import com.acdc.domain.ElectricityMeterActivePower;
import com.acdc.service.IElectricityMeterActivePowerService;
import java.util.Date;
import com.acdc.service.IDlt698LogService;
import com.acdc.domain.Dlt698Log;

@Slf4j
@Component
public class _485AckHandler implements MessageHandler {


    @Autowired
    private GetResponseNormalFrameParser getResponseNormalFrameParser;

    @Autowired
    private ConnectResponseFrameParser connectResponseFrameParser;

    @Autowired
    private IIotModuleService iotModuleService;

    @Autowired
    private IMeterDeviceService meterDeviceService;

    @Autowired
    private IElectricityMeterActivePowerService electricityMeterActivePowerService;

    @Autowired
    private IDlt698LogService dlt698LogService;

    @Override
    public void handleMessage(String topic, String message) {
        String imei = topic.split("\\/")[2];
        log.info("IMIEI: {}, 485AckHandler: {}", imei, message);

        try {
            MqttMsg<_485Ack> mqttMsg = new ObjectMapper().readValue(message, new TypeReference<MqttMsg<_485Ack>>() {});
            _485Ack _485Ack = mqttMsg.getData();
            String dat = _485Ack.getDat();
            byte[] responseBytes = HexUtils.hexStringToBytes(dat);
            
            try {
                GetResponseNormalFrame frame = getResponseNormalFrameParser.parseFrame(responseBytes);
                Object data = getResponseNormalFrameParser.getData(frame);
                if (data instanceof ForwardPower) {
                    ForwardPower forwardPower = (ForwardPower)data;
                    log.info("Forward Power: {}", forwardPower);
                    // 保存电能正向有功功率记录
                    String serverAddress = forwardPower.getServerAddress();
                    MeterDevice meterDevice = meterDeviceService.selectMeterDeviceByServerAddress(serverAddress);
                    ElectricityMeterActivePower electricityMeterActivePower = new ElectricityMeterActivePower();
                    electricityMeterActivePower.setElectricityMeterId(meterDevice.getId());
                    electricityMeterActivePower.setActivePower(forwardPower.getPower());
                    electricityMeterActivePower.setCollectionTime(new Date());
                    electricityMeterActivePowerService.insertElectricityMeterActivePower(electricityMeterActivePower);
                    saveInstructionLog(imei, serverAddress, "power_response", responseBytes);
                } else if (data instanceof String) {
                    String serverAddress = (String)data;
                    log.info("Server Address: {}", serverAddress);
                    // 关联物联网模块与ServerAddress关联
                    IotModule iotModule = iotModuleService.selectIotModuleByImei(imei);
                    if (iotModule != null) {
                        MeterDevice meterDevice = meterDeviceService.selectMeterDeviceByServerAddress(serverAddress);
                        if (meterDevice != null) {
                            meterDevice.setIotModuleId(iotModule.getId());
                            meterDeviceService.updateMeterDevice(meterDevice);
                        }
                    }
                    saveInstructionLog(imei, serverAddress, "server_addr_response", responseBytes);
                }
            } catch (RuntimeException e) {
                log.error("485AckHandler: {}", e.getMessage());
                ConnectResponseFrame frame = connectResponseFrameParser.parseFrame(responseBytes);
                log.info("Connect Response Frame: {}", frame);
                String serverAddress = frame.getAddressDomain().getServerAddress();
                MeterDevice meterDevice = meterDeviceService.selectMeterDeviceByServerAddress(serverAddress);
                if (meterDevice != null) {
                    meterDevice.setDeviceStatus("2");
                    meterDeviceService.updateMeterDevice(meterDevice);
                }
                saveInstructionLog(imei, serverAddress, "connect_response", responseBytes);
            }
        } catch (JsonProcessingException e) {
            log.error("485AckHandler: {}", e.getMessage());
        }
    }

    /**
     * 保存指令日志
     * @param imei IMEI号
     * @param serverAddress 服务器地址
     * @param msgType 消息类型
     * @param frameBytes 指令字节数组
     */
    private void saveInstructionLog(String imei, String serverAddress, String msgType, byte[] frameBytes) {
        try {
            IotModule iotModule = iotModuleService.selectIotModuleByImei(imei);
            if (iotModule == null) {
                log.warn("未找到IMEI为{}的IoT模块", imei);
                return;
            }
            
            MeterDevice meterDevice = null;
            if (serverAddress != null) {
                meterDevice = meterDeviceService.selectMeterDeviceByServerAddress(serverAddress);
                if (meterDevice == null) {
                    log.warn("未找到服务器地址为{}的计量设备", serverAddress);
                }
            }
            
            Dlt698Log dlt698Log = new Dlt698Log();
            dlt698Log.setIotModuleId(iotModule.getId());
            dlt698Log.setMsgType(msgType);
            dlt698Log.setDeviceId(meterDevice != null ? meterDevice.getId() : null);
            dlt698Log.setMsgData(HexUtils.bytesToHex(frameBytes).replaceAll(" ", ""));
            dlt698Log.setCreateTime(new Date());
            dlt698LogService.insertDlt698Log(dlt698Log);
            
            log.debug("成功保存指令日志: IMEI={}, 消息类型={}", imei, msgType);
        } catch (Exception e) {
            log.error("保存指令日志失败: IMEI={}, 消息类型={}, 错误信息={}", imei, msgType, e.getMessage(), e);
        }
    }
}
